package com.fdl.dao.model.security;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.UserDetails;

import com.fdl.common.exception.security.DeleteUserSelfException;
import com.fdl.common.exception.security.DuplicateLoginidException;
import com.fdl.common.exception.security.LoginTimeOutException;
import com.fdl.dao.base.Dao;
import com.fdl.dao.security.UserDao;
import com.fdl.service.security.impl.SecurityUtils;

/**
 * 
 * @description 
 * @project: HRM
 * @Date:2011-2-12
 * @version  1.0
 * @Company: 33e9
 * @author jun.wen
 */
public class User  implements UserDetails,Serializable  {
	/**
	 * 
	 */
	private static final long serialVersionUID = 2162408615151130698L;

	public static Set customAuthorities = new HashSet(0);

	public final static String STATUS_ENABLE = "1";

	public final static String STATUS_DISABLE = "0";
	
	public final static String STATUS_DELETE = "-1";

	protected static UserDao userDao;

	private Long id;

	/**
	 ID	id主键	NUMBER(10)	10		TRUE	FALSE	TRUE
	 */
	public Long getId() {
		return id;
	}
	/**
	 ID	id主键	NUMBER(10)	10		TRUE	FALSE	TRUE
	 */
	public void setId(Long id) {
		this.id = id;
	}

	private String loginid;

	private String password;
	
	private String name;
	
	private String gender;

	private String status = STATUS_ENABLE;

	private long loginTimes;

	private Date lastLoginTime;

	private String lastLoginAddress;

	private Set roles = new HashSet(0);

	private GrantedAuthority[] authorities;

	public User() {}

	/**
	  PWD	密码	VARCHAR2(45)	45		FALSE	FALSE	FALSE
	 */
	public String getPassword() {
		return password;
	}
	/**
	  PWD	密码	VARCHAR2(45)	45		FALSE	FALSE	FALSE
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	protected Dao getDao() {
		return userDao;
	}
	/**
	  USER_ID	用户登陆帐号	VARCHAR2(255)	255		FALSE	FALSE	TRUE
	 **/
	public String getLoginid() {
		return this.loginid;
	}
	/**
	  USER_ID	用户登陆帐号	VARCHAR2(255)	255		FALSE	FALSE	TRUE
	 **/
	public void setLoginid(String loginid) {
		this.loginid = loginid;
	}
	
	/**
	 * NAME	用户姓名	VARCHAR2(255)	255		FALSE	FALSE	FALSE
	 * @return
	 */
	public String getName() {
		return name;
	}
	/**
	 * NAME	用户姓名	VARCHAR2(255)	255		FALSE	FALSE	FALSE
	 * @return
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 GENDER	GENDER	性别 0 男  1 女 2 保密	VARCHAR2(2)	2		FALSE	FALSE	FALSE 
	 * @return
	 */
	public String getGender() {
		return gender;
	}
	/**
	 GENDER	GENDER	性别 0 男  1 女 2 保密	VARCHAR2(2)	2		FALSE	FALSE	FALSE 
	 * @return
	 */
	public void setGender(String gender) {
		this.gender = gender;
	}

	/**
	STATUS	状态 0 停用 1：可用 -1 删除	VARCHAR2(2)	2		FALSE	FALSE	TRUE 
	 * @return
	 */
	public String getStatus() {
		return this.status;
	}
	/**
	STATUS	状态 0 停用 1：可用 -1 删除	VARCHAR2(2)	2		FALSE	FALSE	TRUE 
	 * @return
	 */
	public void setStatus(String status) {
		this.status = status;
	}
	/**
	 当前用户所拥有的角色
	 * @return
	 */
	public Set getRoles() {
		return this.roles;
	}
	/**
	 当前用户所拥有的角色
	 * @return
	 */
	public void setRoles(Set roles) {
		this.roles = roles;
	}
	/**
	 当前用户的状态是否不为 0 停用 
	 * @return
	 */
	public boolean isEnabled() {
		return ((this.status != null) && !this.status.equals(STATUS_DISABLE));
	}

	/**
     LOGIN_TIMES	登陆次数	NUMBER(10)	10		FALSE	FALSE	FALSE
	 * @return
	 */
	public long getLoginTimes() {
		return loginTimes;
	}
	/**
    LOGIN_TIMES	登陆次数	NUMBER(10)	10		FALSE	FALSE	FALSE
	 * @return
	 */
	public void setLoginTimes(long loginTimes) {
		this.loginTimes = loginTimes;
	}

	public static void setUserDao(UserDao userDao) {
		User.userDao = userDao;
	}

	/**
	 * 通过user_id查询user
	 * @param loginid
	 * @return
	 */
	public static User loadByUserID(String loginid) {
		return userDao.loadUserByUserLoginID(loginid);
	}

	public static User loadById(Serializable id) {
		return userDao.get(id);
	}

	/**
     LAST_LOGIN_ADDRESS	登陆IP地址	VARCHAR2(255)	255		FALSE	FALSE	FALSE
	 * @return
	 */
	public String getLastLoginAddress() {
		return lastLoginAddress;
	}
	/**
    LAST_LOGIN_ADDRESS	登陆IP地址	VARCHAR2(255)	255		FALSE	FALSE	FALSE
	 * @return
	 */
	public void setLastLoginAddress(String lastLoginAddress) {
		this.lastLoginAddress = lastLoginAddress;
	}

	/**
	 * 重新设置用户角色
	 * @param aRoles
	 */
	public void resetRoles(Set aRoles) {
		roles = aRoles;
	}

	/**
	 * 判断登陆名是否存在
	 * @throws DuplicateLoginidException
	 */
	public void checkLoginidExist() throws DuplicateLoginidException {
		if (userDao.getCountWithSameLoginid(this) != 0) {
			throw new DuplicateLoginidException();
		}
	}

	/**
	 * 更新
	 * @throws LoginTimeOutException 
	 */
	protected void update() throws LoginTimeOutException {
		updateAuthenticationIfNeed();
		userDao.saveOrUpdate(this);
	}
	
	/**
	 * 获取所有非删除用户（慎用）
	 * @return 
	 */
	public static List getAll() {
		return userDao.getUsersList();
	}

	/**
	 * 用户状态设为可用
	 */
	public void enable() {
		status = User.STATUS_ENABLE;
		userDao.saveOrUpdate(this);
	}

	/**
	 * 用户状态设为停用
	 */
	public void disable() {
		status = User.STATUS_DISABLE;
		userDao.saveOrUpdate(this);
	}

	/**
	 * 假删除,把状态设置为-1
	 * 用户自己不能删除自己
	 * @throws DeleteUserSelfException
	 * @throws LoginTimeOutException 
	 */
	public void delete() throws DeleteUserSelfException, LoginTimeOutException {
		//验证当前用户是否在操作本身
		if (SecurityUtils.getCurrentUser().getId().equals(getId())) {
			throw new DeleteUserSelfException();
		}

		this.status = STATUS_DELETE;
	}

	/**
	 * 根据角色获取停用用户
	 * @param role
	 * @return
	 */
	public static List getAvailableUsersByRole(Role role) {
		return userDao.getUsersByRole(role, new String[] { STATUS_DISABLE });
	}


	/**
	 * 获取当前用户所有权限
	 * return GrantedAuthority[]
	 */
	public GrantedAuthority[] getAuthorities() {
		if (authorities == null) {
			Set set = new HashSet();
			Iterator roleIt = roles.iterator();
			while (roleIt.hasNext()) {
				Role role = (Role) roleIt.next();
				Iterator permissionIt = role.getPermissions().iterator();

				while (permissionIt.hasNext()) {
					set.add(new GrantedAuthorityImpl(((Permission) permissionIt.next())
							.getName()));
				}
			}
			set.addAll(customAuthorities);
			authorities = (GrantedAuthority[]) set
					.toArray(new GrantedAuthority[] {

					});
		}
		return authorities;
	}

	public String getUsername() {
		return loginid;
	}

	public boolean isAccountNonExpired() {
		return true;
	}

	public boolean isAccountNonLocked() {
		return true;
	}

	public boolean isCredentialsNonExpired() {
		return true;
	}

	private void updateAuthenticationIfNeed() throws LoginTimeOutException {
		if (SecurityUtils.getCurrentUser().getId().equals(getId())) {
			SecurityUtils.setCurrentUser(this);
		}
	}

	/**
	 * 当前用户是否拥有此角色
	 * @param role
	 * @return
	 */
	public boolean hasRole(Role role) {
		return roles.contains(role);
	}

	public static void setCustomAuthorities(Set customAuthorities) {
		User.customAuthorities = customAuthorities;
	}
	
	/**
	 * 当前用户是否有此权限
	 * @param auth
	 * @return
	 */
	public boolean hasPermission(String auth) {
		Iterator it = roles.iterator();
		while (it.hasNext()) {
			if (((Role) it.next()).hasPermission(auth))
				return true;
		}
		return false;
	}

	/**
	  LAST_LOGIN_TIME	最后登陆时间	DATE			FALSE	FALSE	FALSE
	 * @return
	 */
	public Date getLastLoginTime() {
		return this.lastLoginTime;
	}
	/**
	  LAST_LOGIN_TIME	最后登陆时间	DATE			FALSE	FALSE	FALSE
	 * @return
	 */
	public void setLastLoginTime(Date lastLoginTime) {
		this.lastLoginTime = lastLoginTime;
	}

	public void save() {
		userDao.saveOrUpdate(this);
	}

}
